
#ifndef _ARBOLBMAS_H_
#define _ARBOLBMAS_H_

#include "../EstructurasArbol//Clave.h"
#include "../ManejadorFuncionesArbol/Persistor.h"
#include "Interno.h"
#include "Hoja.h"
#include "../EstructurasArbol/Constantes.h"
#include "../ManejadorFuncionesArbol/EscritorNodo.h"
#include "../ManejadorFuncionesArbol/LectorDeNodos.h"

using namespace std;



class ArbolBMas {

	friend class Nodo;
	friend class Interno;
	friend class Hoja;

private:

	Nodo* raiz;
	string path_file;
	int contador_de_nodos;
	int primeraHoja;

	long block_Size;
	unsigned int control_Data_Size;

	LectorDeNodos* lector_Nodos;
	EscritorNodo* escritor_Nodos;


public:

	ArbolBMas(std::string ruta_archivo, unsigned int M);
	~ArbolBMas();

	/*Inserta un registro en el Arbol B+*/
	bool insertar(Registro* elemento);

	/*Busca un termino dentro del arbol y devuelve el registro que lo contiene,
	 * sino lo encuentra devuelve el proximo elemento mas grande.
	 */
	Registro* buscar(string clave);

	/*Guarda los terminos que tiene el registro en forma ordenada en un archivo de texto*/
	void EscribirListadoOrdenado();



	bool es_nula_la_raiz (){
		return (raiz==NULL);
	}

	void MostrarArbol ();


private:


	void inicializar_raiz();

	Hoja* obtener_Hoja();
	Interno* obtener_Nodo_Interno(int nivel);
	int obtener_Posicion_Insercion(Nodo *nodo, Clave clave);
	int obtener_IdNodo();


	bool insertar_Recursivo(Nodo* nodo_actual,  Registro* registro, Clave* new_key_root, Nodo** new_node);
	int insertar_en_hoja(Hoja* nodo_actual, Registro* registro);

	Registro* buscar_Recursivo(Clave termino, Nodo* nodo);

	void toString(Nodo* nodo, int tab, ofstream& fo);
	void toString_listado(Nodo* nodo, ofstream& file_list);

	void guardar_Nodo_en_Bloque(Nodo* nodo);
	Nodo* obtener_Nodo_desde_Bloque(int id_Nodo);
	void liberar_Memoria_Nodo(Nodo* nodo);

	void quitar_FrontCoding_Nodo (Nodo ** nodo);
	void quitar_FrontCoding_Hoja (Hoja ** nodo);
	void aplicar_FrontCoding_Hoja(Hoja** hoja_actual);
	void aplicar_FrontCoding(Nodo** nodo);

	void split_Nodo_Interno(Interno* interno_actual, Clave* new_key_root, Nodo** new_interno, int nueva_posicion);
	void split_Hoja(Hoja* n_hoja, Clave* clave_promovida, Nodo** nueva_hoja);

	void inicializar_archivos_de_bloques(string ruta);


};

#endif // _ARBOLBMAS_H_
